package rules

import (
	"fmt"
	"strings"

	"ddl_checker/internal/parser"
)

// TableRelationshipRule 表关联检查规则
type TableRelationshipRule struct{}

// Name 规则名称
func (r *TableRelationshipRule) Name() string {
	return "表关联检查"
}

// Check 执行检查
func (r *TableRelationshipRule) Check(data DDLCheckData) CheckResult {
	result := CheckResult{
		Status:  StatusPassed,
		Details: make([]string, 0),
	}

	// 如果没有Schema或Table，跳过检查
	if strings.TrimSpace(data.Schema) == "" || strings.TrimSpace(data.Table) == "" {
		result.Details = append(result.Details, "⚠️ 未提供Schema或Table信息，跳过表关联检查")
		result.Status = StatusSkipped
		return result
	}

	expectedFormat := fmt.Sprintf("%s.%s", data.Schema, data.Table)

	// 检查DDL脚本
	hasDDL := strings.TrimSpace(data.Script) != ""
	hasRollback := strings.TrimSpace(data.RollbackScript) != ""

	if !hasDDL && !hasRollback {
		// 两个脚本都没有，跳过检查
		result.Details = append(result.Details, "⚠️ 未提供DDL脚本和回滚脚本，跳过表关联检查")
		result.Status = StatusSkipped
		return result
	}

	if hasDDL {
		ddlDetails := r.checkScriptTableRelationship(data.Script, expectedFormat, "DDL脚本")
		result.Details = append(result.Details, ddlDetails...)
		if !r.allPassed(ddlDetails) {
			result.Status = StatusFailed
		}
	}

	if hasRollback {
		rollbackDetails := r.checkScriptTableRelationship(data.RollbackScript, expectedFormat, "回滚脚本")
		result.Details = append(result.Details, rollbackDetails...)
		if !r.allPassed(rollbackDetails) {
			result.Status = StatusFailed
		}
	}

	return result
}

// checkScriptTableRelationship 检查脚本的表关联关系
func (r *TableRelationshipRule) checkScriptTableRelationship(script, expectedTable, scriptType string) []string {
	details := []string{fmt.Sprintf("### %s表关联检查", scriptType)}

	if strings.TrimSpace(script) == "" {
		details = append(details, "⚠️ 未提供脚本，跳过检查")
		details = append(details, "")
		return details
	}

	// 使用混合分析器分割语句
	analyzer := parser.NewHybridAnalyzer()
	statements, err := analyzer.ParseBatchDDL(script, ";")
	if err != nil {
		// 如果解析失败，回退到原始方法
		if strings.Contains(script, expectedTable) {
			details = append(details, fmt.Sprintf("✅ %s正确操作了指定的表: %s", scriptType, expectedTable))
		} else {
			details = append(details, fmt.Sprintf("❌ %s应操作指定的表: %s", scriptType, expectedTable))
		}
		details = append(details, "")
		return details
	}

	// 如果没有语句，返回false
	if len(statements) == 0 {
		details = append(details, "⚠️ 未找到有效的SQL语句")
		details = append(details, "")
		return details
	}

	// 检查每个语句是否包含期望的表名
	allValid := true
	for i, stmt := range statements {
		if r.containsTable(stmt, expectedTable) {
			details = append(details, fmt.Sprintf("✅ 语句%d正确操作了指定的表: %s", i+1, expectedTable))
		} else {
			details = append(details, fmt.Sprintf("❌ 语句%d应操作指定的表: %s", i+1, expectedTable))
			allValid = false
		}
	}

	if allValid {
		if len(statements) == 1 {
			details = append(details, fmt.Sprintf("✅ %s正确操作了指定的表: %s", scriptType, expectedTable))
		} else {
			details = append(details, fmt.Sprintf("✅ %s所有语句都正确操作了指定的表", scriptType))
		}
	} else {
		if len(statements) == 1 {
			details = append(details, fmt.Sprintf("❌ %s应操作指定的表: %s", scriptType, expectedTable))
		} else {
			details = append(details, fmt.Sprintf("❌ %s部分语句未正确操作指定的表", scriptType))
		}
	}

	details = append(details, "")
	return details
}

// containsTable 检查单个SQL语句是否包含指定表名
func (r *TableRelationshipRule) containsTable(stmt *parser.DDLStatement, expectedTable string) bool {
	// 检查解析出的表
	for _, table := range stmt.Tables {
		if table == expectedTable {
			return true
		}
	}

	// 检查原始SQL中是否包含表名（作为备用方案）
	return strings.Contains(strings.ToUpper(stmt.OriginalSQL), strings.ToUpper(expectedTable))
}

// allPassed 检查所有检查项是否都通过
func (r *TableRelationshipRule) allPassed(details []string) bool {
	for _, detail := range details {
		if strings.Contains(detail, "❌") {
			return false
		}
	}
	return true
}
